package com.itheima.leetcode.od.b.sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.stream.Collectors;

/**
 * (C卷,100分)- 手机App防沉迷系统（Java & JS & Python & C）
 * <p>
 * 题目描述
 * <p>
 * 智能手机方便了我们生活的同时，也侵占了我们不少的时间。“手机App防沉迷系统”能够让我们每天合理地规划手机App使用时间，在正确的时间做正确的事。
 * <p>
 * 它的大概原理是这样的：
 * <p>
 * 在一天24小时内，可以注册每个App的允许使用时段
 * <p>
 * 一个时间段只能使用一个App
 * <p>
 * App有优先级，数值越高，优先级越高。注册使用时段时，如果高优先级的App时间和低优先级的时段有冲突，则系统会自动注销低优先级的时段，如果App的优先级相同，则后添加的App不能注册。
 * <p>
 * 请编程实现，根据输入数据注册App，并根据输入的时间点，返回时间点使用的App名称，如果该时间点没有注册任何App，请返回字符串“NA”。
 * <p>
 * 输入描述
 * <p>
 * 第一行表示注册的App数量 N（N ≤ 100）
 * <p>
 * 第二部分包括 N 行，每行表示一条App注册数据
 * <p>
 * 最后一行输入一个时间点，程序即返回该时间点使用的App
 * <p>
 * 2
 * <p>
 * App1 1 09:00 10:00
 * <p>
 * App2 2 11:00 11:30
 * <p>
 * 09:30
 * <p>
 * 数据说明如下：
 * <p>
 * N行注册数据以空格分隔，四项数依次表示：App名称、优先级、起始时间、结束时间
 * <p>
 * 优先级1~5，数字越大，优先级越高
 * <p>
 * 时间格式 HH:MM，小时和分钟都是两位，不足两位前面补0
 * <p>
 * 起始时间需小于结束时间，否则注册不上
 * <p>
 * 注册信息中的时间段包含起始时间点，不包含结束时间点
 * <p>
 * 输出描述
 * <p>
 * 输出一个字符串，表示App名称，或NA表示空闲时间
 * <p>
 * 用例
 * <p>
 * 输入	1
 * <p>
 * App1 1 09:00 10:00
 * <p>
 * 09:30
 * <p>
 * 输出	App1
 * <p>
 * 说明	App1注册在9点到10点间，9点半可用的应用名是App1
 * <p>
 * 输入	2
 * <p>
 * App1 1 09:00 10:00
 * <p>
 * App2 2 09:10 09:30
 * <p>
 * 09:20
 * <p>
 * 输出	App2
 * <p>
 * 说明	App1和App2的时段有冲突，App2优先级高，注册App2之后，App1自动注销，因此输出App2。
 * <p>
 * 输入	2
 * <p>
 * App1 1 09:00 10:00
 * <p>
 * App2 2 09:10 09:30
 * <p>
 * 09:50
 * <p>
 * 输出	NA
 * <p>
 * 说明	无
 * <p>
 * 题目解析
 * <p>
 * 本题数量级较小，可以考虑暴力破解。
 * <p>
 * 本题每注册一个App_registering前，都要去和已注册的所有App_registered进行比较：
 * <p>
 * 注册时段是否有冲突？
 * <p>
 * 如果没有冲突，则继续和下一个App_registered比较
 * <p>
 * 如果有冲突，则比较优先级
 * <p>
 * 2.1. App_registering 的优先级高于（>）App_registered，则App_registered需要被注销，此时不能直接进行注销动作，因为我们需要确保 App_registering 可以注册后，才能进行注销。
 * <p>
 * 2.2. App_registering 的优先级不高于（≤）App_registered，则App_registering不能注册，即终止后续比较
 * <p>
 * 本题比较两个App注册时段冲突的方式，可以将App的注册时段的时间点信息，转化为分钟数数值，比如：
 * <p>
 * 10:29
 * <p>
 * 可以转化为：
 * <p>
 * 10 * 60 + 29 = 629
 * <p>
 * 这样两个App的时段比较，其实判断两个区间是否有交集，假设两个时段分别为
 * <p>
 * [s1, e1] 和 [s2, e2]
 * <p>
 * 只要满足
 * <p>
 * s1 >= e2 或者 s2 >= e1 即可说明两个区间无交集，注意根据题目说明
 * <p>
 * 注册信息中的时间段包含起始时间点，不包含结束时间点
 * <p>
 * 上面两个区间均为左闭右开区间。
 * <p>
 * 且区间保证左边界>右边界，因为题目说明
 * <p>
 * 起始时间需小于结束时间，否则注册不上
 * <p>
 * 即，一个App是否可以注册需要先判断其左边界是否大于右边界
 */
public class AppAntiAddictionSystem {
    public static void main(String[] args) {
        /*Scanner sc = new Scanner(System.in);

        int n = sc.nextInt();

        // 需要注册的App
        ArrayList<App> apps = new ArrayList<>();
        for (int i = 0; i < n; i++) {
            apps.add(new App(sc.next(), sc.nextInt(), convert(sc.next()), convert(sc.next())));
        }

        // 需要查询的时间点
        int queryTime = convert(sc.next());*/

        int n = 1;

        // 需要注册的App
        String input1 = "App1 1 09:00 10:00";
        ArrayList<App> apps = Arrays.stream(input1.split("\n"))
                .map(s -> {
                    String[] arr = s.split(" ");
                    return new App(arr[0], Integer.parseInt(arr[1]), convert(arr[2]), convert(arr[3]));
                })
                .collect(Collectors.toCollection(ArrayList::new));

        String input2 = "09:30";
        // 需要查询的时间点
        int queryTime = convert(input2);

        System.out.println(getResult(apps, queryTime));
    }

    public static String getResult(ArrayList<App> apps, int queryTime) {
        // 记录已注册的App
        ArrayList<App> registereds = new ArrayList<>();

        outer:
        for (App app : apps) {
            // 起始时间>=结束时间，则注册不上
            if (app.startTime >= app.endTime) {
                continue;
            }

            // 记录已注册的App中被注销的App的位置
            ArrayList<Integer> idxs = new ArrayList<>();

            // 比较app_registering和它前面完成注册的所有app_registered
            for (int j = 0; j < registereds.size(); j++) {
                App registered = registereds.get(j);

                // 两个App的注册时间无冲突，则继续和下一个app_registered比较
                if (registered.startTime >= app.endTime || app.startTime >= registered.endTime){
                    continue;
                }

                // 两个App的注册时间有冲突，则比较优先级
                if (app.priority > registered.priority) {
                    // 这里不能直接注销低优先级的app_registered，我们要保证app_registering一定能注册后才能进行此操作，因此先记录要被注销的app_registered的位置
                    idxs.add(j);
                } else {
                    // app_registering的优先级 <= app_registered的优先级时，则app_registering不能注册，终止比较
                    continue outer;
                }
            }

            // idxs中索引是升序的，如果正序删除的话，那么每删除一个元素，都会改变后面元素的索引位置，因此这里采用倒序删除
            for (int j = idxs.size() - 1; j >= 0; j--) {
                int deleteIdx = idxs.get(j);
                registereds.remove(deleteIdx);
            }

            registereds.add(app);
        }

        String ans = "NA";

        // 注册成功的App时段之间互不冲突，因此queryTime只会对应一个App
        for (App app : registereds) {
            if (queryTime >= app.startTime && queryTime < app.endTime) {
                ans = app.name;
                break;
            }
        }

        return ans;
    }

    public static int convert(String time) {
        // 时间格式 HH:MM，小时和分钟都是两位，不足两位前面补0
        String[] tmp = time.split(":");

        String hours = tmp[0];
        String minutes = tmp[1];
        return Integer.parseInt(hours) * 60 + Integer.parseInt(minutes);
    }

    static class App {
        String name;
        int priority;
        int startTime;
        int endTime;

        public App(String name, int priority, int startTime, int endTime) {
            this.name = name;
            this.priority = priority;
            this.startTime = startTime;
            this.endTime = endTime;
        }
    }
}